; -*- mode: clojure; -*-
; vim: filetype=clojure

(require '[clojure.java.io :as javaio])
(require '[clojure.string :as string])
(require 'once)

(let [host "0.0.0.0"]
  (tcp-server {:host host})
  (udp-server {:host host})
  (ws-server  {:host host}))

(periodically-expire 5 {:keep-keys [:host :service :metric :ttl]})

; -----------------------------------
(def conf-dir "/satori-conf")

(use 'lib :reload)
(use 'alarm :reload)
(use 'agent-plugin :reload)
(use 'hostgroup :reload)

(set-alarm-redis! "redis://redis:6379/0")
(set-master-redis! "redis://redis:6379/0")

(set-plugin-repo! conf-dir)

(def selftest-rules
  (sdo
    (where (service ".satori.riemann.newconf")
      (! {:note "监控规则更新了"
          :event? true
          :level 3
          :groups [:operation]}))
    (where (service ".satori.riemann.reload-failed")
      (! {:note "监控规则 Reload 失败"
          :event? true
          :level 3
          :groups [:operation]}))
    (where (service ".satori.agent.plugin.error")
      (throttle 1 120
        (! {:note "Satori 插件执行出错"
            :event? true
            :level 5
            :groups [:operation]})))
    (where (service ".satori.agent.crash")
      (throttle 1 120
        (! {:note "Satori Agent 崩溃"
            :event? true
            :level 3
            :groups [:operation]})))
    (where (service ".satori.agent.plugin.signature-fail")
      (throttle 1 600
        (! {:note "Satori 规则仓库签名无效"
            :event? true
            :level 5
            :groups [:operation]})))
    (where (service #"^\.satori\.agent\.plugin")
      (by [:service :file]
        (throttle 1 120
          (where (service ".satori.agent.plugin.timeout")
            (! {:note "Satori 插件执行超时"
                :event? true
                :level 5
                :groups [:operation]}))
          (where (service ".satori.agent.plugin.no-stdout")
            (! {:note "Satori 插件无输出"
                :event? true
                :level 6
                :groups [:operation]}))
          (where (service ".satori.agent.plugin.cant-kill")
            (! {:note "无法终止超时的 Satori 插件"
                :event? true
                :level 5
                :groups [:operation]}))
          (where (service ".satori.agent.plugin.bad-format")
            (! {:note "Satori 插件输出格式错误"
                :event? true
                :level 5
                :groups [:operation]})))))))

(def selftest-report-exceptions
  (throttle 1 30
    (smap #(event {:host "Satori"
                   :service ".satori.riemann.runtime-exception"
                   :time (:time %)
                   :description (:description %)})
      (! {:note "监控规则有运行时错误！"
          :event? true
          :level 5
          :groups [:operation]}))))

(def rules
  (doall (flatten
    (for [d (.listFiles (javaio/file (str conf-dir "/rules"))) :when (.isDirectory d)]
      (for [f (.listFiles d) :when (.endsWith (.getName f) ".clj")]
        (let [[_ category module] (re-find #"([a-z0-9_-]+)/([a-z0-9_-]+)\.clj" (.getPath f))
              category (string/replace category \_ \-)
              module (string/replace module \_ \-)
              full-ns (symbol (format "%s.%s" category module))]
          (require full-ns :reload)
          (info "Reloaded" full-ns)
          (for [[k v] (ns-publics (find-ns full-ns)) :when (.endsWith (str k) "-rules")]
            @v)))))))

(streams
  (exception-stream selftest-report-exceptions
    selftest-rules
    (apply sdo rules)))
